인증·인가 방식 비교 (API Key·OAuth2·JWT·HMAC·mTLS)

서버 간, 사용자 간 통신에서 “누구인가”를 확인하는 대표 방식들의 차이와 쓰임을 정리한다. 용어 정의는 IT 용어집 - 보안·인증 참고.

1. 먼저 용어 구분

용어질문예
인증(authentication)너는 누구인가?로그인, 인증서 검증
인가(authorization)그 사람이 이것을 해도 되는가?관리자만 접근, 경로별 허용
암호화(encryption)내용을 숨긴다(키가 있으면 복호화 가능)TLS, AES
해싱(hashing)되돌릴 수 없는 고정 길이 값으로 바꾼다비밀번호 저장
서명(signature)누가 보냈고 바뀌지 않았음을 증명한다JWT 서명, HMAC

비밀번호는 암호화가 아니라 해싱해서 저장한다.

2. 방식 한눈에 비교

방식핵심주 용도약점
API key미리 발급한 고정 키를 헤더에 넣음간단한 서버 간 인증키가 요청에 실려 가서 탈취되면 끝
OAuth2비밀번호를 넘기지 않고 권한을 위임받아 access token 발급제3자 앱 연동(“○○로 로그인”)흐름이 복잡, 토큰 관리 필요
JWT서명된 자가 포함(self-contained) 토큰. 서버가 DB 조회 없이 검증사용자 세션, 서비스 간 사용자 정보 전달발급 후 폐기하기 어려움, 내용은 암호화가 아님
HMAC signature공유 비밀키 + 메시지로 서명웹훅, 요청 위변조 방지비밀키를 양쪽이 공유해야 함
mTLS서버뿐 아니라 클라이언트도 인증서로 신원 증명서비스 간 통신, 금융 대외 연동인증서 발급·갱신 운영 부담

3. API key

GET /orders
X-API-Key: sk_live_abc123
  • 가장 단순하다. 서버는 키 목록과 비교만 한다.
  • 키 자체가 네트워크로 전달되므로 TLS 필수이고, 노출되면 다른 사람이 그대로 쓸 수 있다.
  • 키에 만료와 권한 범위를 두지 않으면 폐기·교체가 어렵다.

4. OAuth2 (권한 위임)

“사용자가 앱 A에게, 서비스 B의 자원에 대한 제한된 권한을 위임”하는 표준이다. 비밀번호를 앱 A에 주지 않고 access token만 준다.

sequenceDiagram
    participant U as 사용자
    participant A as 앱(클라이언트)
    participant AS as 인가 서버
    participant R as 자원 서버
    U->>A: 로그인 요청
    A->>AS: 인가 요청 (scope)
    AS->>U: 로그인·동의 화면
    U->>AS: 동의
    AS->>A: authorization code
    A->>AS: code로 token 요청
    AS->>A: access token
    A->>R: access token으로 자원 요청
  • 소셜 로그인의 전체 흐름은 소셜로그인 전 과정 참고.
  • access token은 수명이 짧고, 갱신은 refresh token으로 한다.

5. JWT (JSON Web Token)

헤더.페이로드.서명
  • 페이로드에 사용자 ID, 권한, 만료 시각(exp)을 담고 서버의 서명 키로 서명한다.
  • 서버는 DB 조회 없이 서명만 검증하면 되어서 확장에 유리하다(stateless).
  • 서명은 위변조를 막을 뿐 내용을 숨기지 않는다(페이로드는 누구나 디코딩해 볼 수 있다). 민감 정보를 넣지 않는다.
  • 한 번 발급하면 만료 전까지 유효해서 즉시 폐기가 어렵다. 수명을 짧게 하고 refresh token을 쓰거나, 폐기 목록을 별도로 관리한다.
  • 서명 방식: HS256(대칭키, 비밀키 공유) / RS256(비대칭키, 개인키로 서명하고 공개키로 검증).

6. HMAC (Hash-based Message Authentication Code)

“공유된 비밀키 + 메시지”를 해시해서 서명을 만든다.

보내는 쪽: signature = HMAC-SHA256(secret, 요청 본문 + timestamp)
           → 요청 헤더에 X-Signature: signature
받는 쪽:   같은 secret으로 직접 계산 → 헤더 값과 비교
  • 보장하는 것: ① 메시지가 중간에 바뀌지 않았다(무결성) ② secret을 아는 상대가 보냈다(인증)
  • 보장하지 않는 것: 암호화가 아니다. 본문은 그대로 보인다.
  • API key와 달리 secret이 네트워크에 실리지 않고 서명만 실린다. 서명에 timestamp(또는 nonce)를 넣으면 **재전송 공격(replay)**도 막는다.
  • 실제 예: GitHub·Stripe 웹훅 서명, AWS API 요청 서명(SigV4)

7. 공개키 / 개인키와 인증서

대칭키비대칭키(공개키 암호)
키하나를 양쪽이 공유한 쌍(공개키, 개인키)
속도빠름느림
문제키를 안전하게 전달해야 함해결 가능

TLS는 비대칭키로 키 교환·인증을 하고, 실제 데이터는 대칭키로 암호화한다.

공개키와 개인키는 쓰임에 따라 방향이 반대다.

목적만드는 쪽확인하는 쪽
암호화(기밀성)상대의 공개키로 암호화상대가 자기 개인키로 복호화
전자서명(인증, 무결성)자기 개인키로 서명누구나 공개키로 검증
  • 개인키가 유출되면 신뢰가 무너지고, 공개키는 유출돼도 문제가 없다.
  • **인증서(certificate)**는 공개키와 소유자 정보를 묶어 인증기관(CA)이 서명한 문서다. “이 공개키는 정말 이 도메인의 것이다”를 보증한다.
  • 파일 무결성을 RSA 서명으로 검증하는 사례는 파일 무결성 전자서명 검증 참고.

8. mTLS (mutual TLS)

일반 TLS는 서버만 인증서로 신원을 증명한다. mTLS는 클라이언트도 인증서를 제시해서 양쪽이 서로를 확인한다.

9. 키 관리: key rotation

암호화 키를 주기적으로 새 버전으로 바꾸는 것이다. 어려운 이유는 v1로 암호화된 기존 데이터는 v1 키로만 풀리기 때문이다.

구성 요소역할예
키 저장소키를 안전하게 보관AWS KMS, HashiCorp Vault, HSM
key rotation 라이브러리애플리케이션이 여러 버전의 키를 다루는 로직Google Tink 등
  1. 암호문 앞에 **키 ID(버전)**를 붙여 저장한다 → [v2][암호문]
  2. **암호화는 항상 최신 키(v2)**로 한다.
  3. 복호화는 암호문에 적힌 버전의 키로 한다(v1 데이터도 계속 읽힌다).
  4. 이후 옛 데이터를 새 키로 **재암호화(migration)**하고 옛 키를 폐기한다.

10. 기타 통제 수단

  • whitelist(allowlist): 허용할 대상(IP, 경로, 호출자)만 목록으로 적고 나머지는 막는다. 외부 연동사의 접근 IP를 제한할 때 쓴다.
  • 마스킹: 개인정보, 카드번호를 일부 가려서 로그에 남긴다. 관련: 제로 디펜던시 개인정보 마스킹과 오류 핑거프린팅
  • 외부에는 내부 유저 ID 대신 해시나 UUID로 만든 별도 키를 제공한다.

11. 어떤 방식을 고를까

상황추천
내부 서비스 간, 간단한 연동API key(+TLS), 더 안전하게는 mTLS
외부 앱이 사용자 권한으로 접근OAuth2
사용자 세션을 서버 확장에 유리하게JWT(수명 짧게)
웹훅, 요청 위변조 방지HMAC signature
호출자 신원을 인증서로 보장해야 함mTLS